<template>
  <view class="auth ">
    <view class="" v-if="pageType==='detail' && readonly!==true">
      <view class="auth-title">
        <view class="">
          角色信息
        </view>
        <view class="">
          <slot name="headBtn">
          </slot>
        </view>
      </view>
      <view class="auth-role-card" v-if="roleNo">
        <view class="auth-role-name">
          角色名称： {{roleModel.role_name||'-'}}
        </view>
        <view class="">
          角色描述:{{roleModel.remark||'-'}}
        </view>
      </view>
    </view>
    <view class="" v-else-if="readonly!==true">
      <view class="auth-role-form">
        <view class="auth-role-form-item">
          <view class="label">
            <text class="text-red">*</text> 角色名称：
          </view>
          <view class="value">
            <uni-easyinput primaryColor='#38C09E' v-model="roleModel.role_name" placeholder="请输入角色名称">
            </uni-easyinput>
          </view>
        </view>
        <view class="auth-role-form-item">
          <view class="label">
            <text style="color: #fff;">*</text>角色描述：
          </view>
          <view class="value">
            <uni-easyinput primaryColor='#38C09E' v-model="roleModel.remark" type="textarea" placeholder="请输入角色描述">
            </uni-easyinput>
          </view>
        </view>
      </view>
    </view>
    <view class="auth-role-wrapper" v-if="pageType==='add'||roleNo">
      <view class="auth-role_title">
        角色权限：<text v-if="readonly===true">{{roleModel.role_name}}</text>
      </view>
      <bx-checkbox-group mode="normal" class="checkbox-group" v-if="pageType==='update'||pageType==='add'">
        <bx-checkbox v-model="cfg.checked" v-for="(cfg,n) in checkCfg" :key="n" :name="cfg.value"
          @change="checkChange(cfg)">
          {{ cfg.label }}
        </bx-checkbox>
      </bx-checkbox-group>
      <view class="auth-role-tree show-y-scroll-bar ">
        <ly-tree ref="authTree" :showCheckbox="true" node-key="fun_no" :tree-data="treeData"
          :defaultExpandAll="defaultExpandAll" :defaultCheckedKeys="defaultCheckedKeys" :checkStrictly="checkStrictly"
          :toggle-expend-all="defaultExpandAll" @node-expand="handleNodeExpand" @node-click="handleNodeClick"
          @check="handleCheck" @check-change="handleCheckChange" />
      </view>
      <view class="align-right" style="height: 8rem;min-height: 8rem;overflow: auto;text-align: right;" v-if="pageType==='detail' && readonly!==true">
        <button class="button lg margin-left" @click="onTap('tapEdit')"><text class="cuIcon-write margin-right"></text>
          编辑</button>
        <button class="line-white button lg bg-red margin-left" @click="onTap('tapDelete')"
          v-if="!roleModel.staff_cnt||roleModel.staff_cnt==='0'"><text
            class="cuIcon-delete margin-right"></text>删除</button>
      </view>
    </view>
    <view class="auth-role-button-box" v-if="pageType==='add'||pageType==='update'">
      <button class="button line-white" @click="cancel" v-if="showCancel">取消</button>
      <button class="button margin-left-lg" @click="onSubmit">确定</button>
    </view>
  </view>
</template>

<script>
  /**
   * AuthTree 权限组件
   * @description 权限编辑、删除、新增、详情 
   * @property {String} pageType = [add|update|Detail] 组件模式 添加、编辑、详情 默认详情 需要传入roleNo
   * @property {String} roleNo - 角色编号 pageType为add或者update时必填
   * @property {String} nodeKey=[fun_no] - 树节点唯一标识字段
   * @property {String} nodeLabel=[fun_name] - 树节点对外显示字段
   * @property {String} terminalType = [一体机|PC] - 终端类型
   * @property {Boolean} showCancel = [true|false] - 编辑、添加状态是否显示取消按钮 默认true
   * @event {Function()} cancel - 编辑或添加模式点击了取消按钮 
   * @event {Function()} submitSuccess - 提交成功 返回提交后的数据
   * @event {Function()} submitFail - 提交失败 返回失败提示
   * @event {Function()} check - 节点选中事件
   * @event {Function()} tapAdd - 右上角新增按钮点击事件
   * @event {Function()} tapEdit - 右上角编辑按钮点击事件
   * @event {Function()} tapDelete - 右上角删除按钮点击事件
   * 内部事件：deleteItem - 删除当前角色，成功返回true及提示，失败返回false及提示；initData 刷新数据；
   * @example <auth-tree :roleNo="roleNo" pageType="update" @check="checkChange" @submit-success="" @submit-fail=""></auth-tree>
   */
  export default {
    data() {
      return {
        checkedObj: {},
        defaultCheckedKeys: [], //默认选中的节点的id集合
        selectList: [],
        treeData: "",
        loading: false,
        roleModel: {
          remark: "",
          role_name: "",
          staff_cnt: ""
        },
        roleData: null, // 回显角色信息
        roleFunData: null, // 默认角色权限合计。
        treeData: [],
        defaultExpandAll: true,
        checkStrictly: false,
        expandedKeys: [],
        authFunListdata: [],
        checkedNodes: [],
        checkCfg: [{
            label: "折叠/展开",
            value: "expand",
            checked: true
          }, {
            label: "全选/全不选",
            value: "checked",
            checked: false
          },
          // {
          //   label: "父子联动",
          //   value: "cascade",
          //   checked: false
          // },
        ]
      }
    },
    props: {
      readonly: {
        type: Boolean,
        default: false
      },
      nodeKey: {
        type: String,
        default: 'fun_no'
      },
      nodeLabel: {
        type: String,
        default: 'fun_name'
      },
      showCancel: {
        type: Boolean,
        default: true
      },
      terminalType: {
        type: String,
        default: '一体机'
      },
      pageType: {
        type: String,
        default: 'detail'
      },
      roleNo: {
        type: String,
        default: ''
      }
    },
    methods: {
      onTap(e) {
        // 触发按钮点击事件
        console.log(`点击了【${e}】按钮`);
        const type = e == 'tapEdit' ? 'update' : e == 'tapDelete' ? 'delete' : 'add'
        this.$emit(e, type, {
          data: this.checkedObj,
          defaultChecked: this.defaultCheckedKeys
        })
      },
      cancel() {
        this.$emit('cancel')
      },
      getCheckedNodes() {
        return this.checkedObj
      },
      // 只有在"点击"修改的指定节点会触发(也就是说这个方法只会触发一次)，obj中包含当前选中
      handleCheck(obj) {
        // obj: {
        // 	checkedKeys: [9, 5], // 当前选中节点的id数组
        // 	checkedNodes: [{...}, {...}], // 当前选中节点数组
        // 	data: {...}, // 当前节点的数据
        // 	halfCheckedKeys: [1, 4, 2], // 半选中节点的id数组
        // 	halfCheckedNodes: [{...}, {...}, {...}], // 半选中节点的数组
        // 	node: Node {...} // 当前节点实例
        // }
        this.checkedObj = obj
        this.$emit('check', obj)
        console.log('handleCheck', obj);
      },

      // 只要节点的选中或半选中状态改变就触发（包括设置默认选中，点击选中/取消选中），其相关的所有父子节点都会触发（也就是说选中一个节点时，触发多次，父子节点的选中状态只要被修改就会触发）
      handleCheckChange(obj) {
        // obj: {
        // 	checked: true, // 节点是否选中
        // 	checkedall: false, // 当前树的所有节点是否全选中
        // 	data: {...}, // 节点数据
        // 	indeterminate: false, // 是否半选中
        // 	node: Node {...} // 节点实例
        // }

        // console.log('handleCheckChange', obj);
      },
      handleNodeClick(obj) {
        // console.log('handleNodeClick', JSON.stringify(obj));
      },
      handleNodeExpand(obj) {
        // console.log('handleNodeExpand', JSON.stringify(obj));
      },
      switchChange(e) {
        this.defaultExpandAll = !this.defaultExpandAll;
      },
      onSubmit() {
        if (!this.roleModel.role_name) {
          uni.showToast({
            title: '请输入角色名称',
            icon: 'none'
          })
          return
        }
        this.loading = true
        uni.showLoading({
          mask: true,
        })
        if (this.pageType == 'update') {
          this.setRoleAuth()
        } else if (this.pageType == 'add') {
          this.setRoleAuth()
        } else if (this.pageType == 'detail') {
          this.loadUpdateDefaultData()
        }
      },
      setReq() {
        let req = {
          "role_name": this.roleModel.role_name,
          "type": this.pageType,
          "remark": this.roleModel.remark,
          "menus": [],
          "funs": [],
          "srvs": []
        }
        let checkedNodes = this.checkedObj.checkedNodes || []
        for (let n in checkedNodes) {
          if (checkedNodes[n].relate_menu_no) {
            req.menus.push(checkedNodes[n].relate_menu_no)
          }
          if (checkedNodes[n].fun_no) {
            req.funs.push(checkedNodes[n].fun_no)
          }
          let srv = {
            "service": "srvtest_table_select",
            "operate_type": "select"
          }

          if (checkedNodes[n].relate_srv) {
            srv = {
              "service": checkedNodes[n].relate_srv,
              "operate_type": checkedNodes[n].srv_type
            }
            req.srvs.push(JSON.stringify(srv))
          }
        }
        req.funs = Array.from(new Set(req.funs))
        req.menus = Array.from(new Set(req.menus))
        req.srvs = Array.from(new Set(req.srvs))
        let arr = req.srvs
        req.srvs = arr.map((item) => JSON.parse(item))
        if (req.funs.length === 0) {
          delete req.funs
        }
        if (req.menus.length === 0) {
          delete req.menus
        }
        if (req.srvs.length === 0) {
          delete req.srvs
        }
        if (this.pageType == 'update') {
          req.role_no = this.roleNo
        }
        return [{
          "serviceName": "srvsys_set_app_role_auth",
          "srvApp": "retail",
          "data": [req]
        }]
      },
      onChange(e) {
        console.log('on-select', e);
        this.selectList = e
      },
      checkChange(e) {
        if (e.value == 'expand') {
          this.defaultExpandAll = !this.defaultExpandAll
        } else if (e.value === "checked") {
          this.$nextTick(() => {
            this.$refs.authTree.setCheckAll(e.checked)
            this.$forceUpdate()
            this.checkedNodes = this.$refs.authTree?.getCheckedNodes()
            this.checkedObj = {
              checkedNodes: this.checkedNodes
            }
          })
        } else {
          this.$nextTick(() => {
            this.checkStrictly = !e.checked
            this.$forceUpdate()
          })
        }
      },
      // 查找默认选中
      async loadUpdateDefaultData() {
        await this.getRoleDetail()
        let req = {
          "serviceName": "srvsys_app_role_fun_select",
          "colNames": [
            "*"
          ],
          "condition": [{
              "colName": "role_no",
              "ruleType": "in",
              "value": this.roleNo
            },
            // {
            //   "colName": "terminal_type",
            //   "ruleType": "in",
            //   "value": this.terminalType
            // },
          ]
        }
        const url = `/retail/select/srvsys_app_role_fun_select`
        const res = await this.$http.post(url, req)
        this.roleFunData = res.data.data
      },
      // 查找角色信息
      getRoleDetail() {
        const url = `/retail/select/srvsys_app_role_select`
        const req = {
          "serviceName": "srvsys_app_role_select",
          "colNames": [
            "*"
          ],
          "condition": [{
            "colName": "role_no",
            "ruleType": "in",
            "value": this.roleNo
          }]
        }
        this.$http.post(url, req).then((res) => {
          this.roleData = res.data.data
          if (res?.data?.data.length > 0) {
            const data = res.data.data[0]
            this.roleModel.role_name = data?.role_name || ""
            this.roleModel.remark = data?.remark || ""
            this.roleModel.staff_cnt = data?.staff_cnt || 0
          }
        })
      },
      setRoleAuth() {
        // 保存权限设置请求
        let req = this.setReq()
        const url = `/retail/operate/srvsys_set_app_role_auth`
        this.$http.post(url, req).then((res) => {
          this.loading = false
          uni.hideLoading()
          if (res.data.state == "SUCCESS" && res.data.resultCode == "SUCCESS") {
            let role_no = res.data.response[0].response.role_no
            if (this.pageType == 'add') {

            } else if (this.pageType == 'update') {
              this.loadUpdateDefaultData()
            }
            this.$emit('submitSuccess', res.data.response[0].response?.msg || res.data.resultMessage,
              res.data
              .response[0].response)
          } else {
            uni.showToast({
              title: res.data.resultMessage,
              icon: 'none'
            })
            this.$emit('submitFail', res.data.resultMessage, )
          }
        })
      },
      // 查找权限树
      getTreeData() {
        let serviceName = "srvsys_fun_auth_def_select"
        const url = `/retail/select/srvsys_fun_auth_def_select`
        let cond = []
        let req = {
          "serviceName": serviceName,
          "colNames": [
            "*"
          ],
          condition: [{
            "colName": "terminal_type",
            "ruleType": "eq",
            value: this.terminalType
          }],
        }
        this.$http.post(url, req).then((res) => {
          console.log(res.data)
          if (this.pageType === 'detail') {
            res.data.data = res.data.data.map(item => {
              item.disabled = true;
              return item
            })
          }

          this.authFunListdata = res.data.data

          if (Array.isArray(this.roleFunData) && this.roleFunData.length > 0) {
            this.defaultCheckedKeys = this.roleFunData.map(item => item.fun_no)
          }
          this.generateOptions(this.authFunListdata)
        })
      },

      // 生成树型数据
      generateOptions(params, checked, expand) {
        var result = []
        for (const param of params) {
          if (param.parent_no == null || param.parent_no == '' || param.parent_no == undefined) { // 判断是否为顶层节点
            let children = this.deepClone(param)
            children['label'] = children[this.nodeLabel]
            children['children'] = this.getchilds(children[this.nodeKey], params) // 获取子节点
            result.push(children)
          }
        }

        this.treeData = result.map((item) => {
          item.name = item.label;
          return item
        })
        uni.hideLoading()
        this.loading = false
      },

      getchilds(nodeKey, array) {
        const childs = []
        for (const arr of array) { // 循环获取子节点
          if (arr['parent_no'] === nodeKey) {
            childs.push(this.deepClone(arr))
          }
        }
        for (const child of childs) { // 获取子节点的子节点
          const childscopy = this.getchilds(child[this.nodeKey], array) // 递归获取子节点
          child['label'] = child[this.nodeLabel]
          child['children'] = childscopy
        }
        return childs
      },
      // 删除当前角色
      deleteItem() {
        const url = `/retail/operate/srvsys_app_role_delete`
        const req = [{
          "serviceName": "srvsys_app_role_delete",
          "condition": [{
            "colName": "role_no",
            "ruleType": "eq",
            "value": this.roleNo
          }]
        }]
        this.$http.post(url, req).then(res => {
          if (res?.data?.state === 'SUCCESS') {
            this.$emit('delete', true, res.data?.response[0]?.response.msg || res?.data?.resultMessage)
          } else {
            this.$emit('delete', false, res?.data?.resultMessage)
          }
        })
      },
      async initData() {
        if (this.roleNo) {
          uni.showLoading({
            mask: true
          })
          this.loading = true
          if (this.pageType == 'update') {
            await this.loadUpdateDefaultData()
          } else if (this.pageType == 'detail') {
            await this.loadUpdateDefaultData()
          } else if (this.pageType == 'add') {

          }
        }
        await this.getTreeData()
      },
    },
    created() {
      this.initData()
    }
  }
</script>

<style lang="scss" scoped>
  .auth {
    display: flex;
    flex-direction: column;
    padding: 3rem;
    border-radius: 1rem;
    background-color: #fff;
    font-size: 2.4rem;
    height: 100%;
    overflow-y: hidden;

    &-title {
      display: flex;
      justify-content: space-between;
      font-size: 2.8rem;
    }

    &-role {
      &-button-box {
        padding: 2rem;
        text-align: center;

        .button {
          min-width: 20rem;
        }
      }

      &-card {
        background-color: #F5F5F5;
        border-radius: 1rem;
        padding: 2.4rem;
        margin: 1.8rem 0;
      }

      &-name {
        font-size: 3rem;
        margin-bottom: 1.5rem;
        font-weight: 700;
      }

      &_title {
        padding: 1rem 0;
      }

      &-tree {
        flex: 1;
        overflow-y: scroll;
      }

      &-form {
        width: 100%;

        &-item {
          width: 100%;
          max-width: 100rem;
          display: flex;
          align-items: center;
          margin-bottom: 1rem;

          .label {
            min-width: 15rem;
          }

          .value {
            flex: 1;
          }
        }
      }

      &-wrapper {
        border: #F5F5F5 1px solid;
        padding: 1.2rem;
        border-radius: 1rem;
        overflow: hidden;
        display: flex;
        flex-direction: column;

        .checkbox-group {
          display: flex;
          align-items: center;
          padding: 2rem 0;
        }

        .check-label {
          display: flex;
          align-items: center;
          margin-right: 2rem;
        }
      }
    }

  }
</style>
